/**
 * JAVACC DEMO 1.0
 * @copy right dwusoft company All rights reserved. 
 * @Package com.dwusoft.buss.common  
 */
package com.dwusoft.ius;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

import com.apache.api.vo.ParamsVo;
import com.apache.cache.util.Validator;
import com.apache.client.InfoReleaseCoreCleint;
import com.apache.exception.BusinessException;
import com.apache.info.entity.PubMetadata;
import com.apache.member.entity.Member;
import com.apache.uct.common.ToolsUtil;
import com.apache.uct.common.entity.Org;
import com.apache.uct.common.entity.User;
import com.dwusoft.ius.plugin.CustomMethodPlugin;

/**
 * description:  生成动态sql
 * @author dyhou 创建时间：2016-8-6  
 */
public class IusSqlTools extends DymicSqlSuper {

	private static IusSqlTools instance;

	private IusSqlTools() {
	}

	public static IusSqlTools getInstance() {
		if (null == instance) {
			instance = new IusSqlTools();
		}
		return instance;
	}

	public static void main(String[] args) {
		ParamsVo vo = new ParamsVo();
		vo.setParams("modelTypes", "pro,pub,deal");
		vo.setParams("pro.proNo", "prono001");
		vo.setParams("pro.proName", "项目测试");
		vo.setParams("pub.proId", "[pro.proId]");
		vo.setParams("pub.proNo", "[pro.proNo]");
		vo.setParams("deal.proId", "[pro.proId]");
		vo.setParams("exe_rules", "pub.proId:[pro.proId],pub.proNo:[pro.proNo],deal.proId:[pro.proId]");
		String sql = IusSqlTools.getInstance().cteageNativeSql(vo, "insert");
		System.out.println("insert==" + sql);
		vo.setParams("pro.w_proName", "dsdsd");
		sql = IusSqlTools.getInstance().cteageNativeSql(vo, "update");
		System.out.println("update==" + sql);

		vo.setParams("modelTypes", "i_pro,u_pub,i_deal");
		vo.setParams("pub.w_proId", "[pro.proId]");
		sql = IusSqlTools.getInstance().cteageNativeSql(vo);
		System.out.println(sql);
	}

	/**
	 * description: 生成原生sql 
	 * @param vo 参数:exe_rules样例:exe_rules=pub.proId:[pro.proId],pub.proNo:[pro.proNo]<br>
	 *             modelTypes样例:modelTypes=pro,pub,deal<br>
	 * @param exeType sql语句类型:insert:插入,update:修改,del删除
	 */
	public String cteageNativeSql(ParamsVo vo, String exeType) {
		String modelTypes = String.valueOf(vo.getParams("modelTypes"));
		String execSql = "";
		//exeCustomPlugin(vo, "befor");
		if (Validator.isNotNull(modelTypes)) {//是否有需要修改的类型
			String str[] = modelTypes.split(",");
			for (int i = 0; i < str.length; i++) {//循环生成sql
				Map<String, String> res = IusClassUtil.getInstance().convert2Map(vo.getParams(), str[i]);
				String sql = "";
				if ("insert".equalsIgnoreCase(exeType)) {
					sql = IusSqlTools.getInstance().createInsertSqlStr(res, str[i], vo);
				} else if ("update".equals(exeType)) {
					sql = IusSqlTools.getInstance().createUpdateSqlStr(res, str[i], vo);
				}
				if (Validator.isNotNull(sql)) {
					execSql += sql + ";";
				}
			}
		} else {
			execSql = String.valueOf(vo.getParams("execSql"));
		}
		//	exeCustomPlugin(vo, "after");
		return execSql;
	}

	/**
	 * description: 生成原生sql <br>
	 * modelTypes=i_pro,i_pub,i_deal或u_pro,u_pub,u_deal (i_表示插入,u_表示修改,d_表示删除)<br>
	 * 待处理字段样例:pub.proId=[pro.proId]<br>
	 * exe_rules样例:exe_rules=pub.proId:[pro.proId],pub.proNo:[pro.proNo]
	 * @param vo
	 */
	public String cteageNativeSql(ParamsVo vo) {
		//	exeCustomPlugin(vo, "befor");
		String execSql = "";
		String modelTypes = String.valueOf(vo.getParams("modelTypes"));
		if (Validator.isNotNull(modelTypes)) {//是否有需要修改的类型
			String str[] = modelTypes.split(",");
			try {
				for (int i = 0; i < str.length; i++) {//循环生成sql  (i_,u_,d_,ib_)
					//					Method method = NetSqlTools.class.getDeclaredMethod(str[i].substring(2) + "Sql", new Class[] {
					//							String.class, ParamsVo.class });
					//					String sql = String.valueOf(method.invoke(this, str[i], vo));
					//					if (Validator.isNotNull(sql)) {
					//						execSql += sql + ";";
					//					}
					execSql += dymicInsertSql(vo, str, i);
				}
			} catch (Exception e) {
				throw new BusinessException(e.getMessage());
			}
		} else {
			execSql = String.valueOf(vo.getParams("execSql"));
		}
		//	exeCustomPluginForAfter(vo, "after");
		System.out.println("execSql=========" + execSql);
		return execSql;
	}

	public String selectNativeSql(ParamsVo vo) {
		String modelTypes = String.valueOf(vo.getParams("modelTypes"));
		String sortCode = String.valueOf(vo.getParams("sortCode"));

		try {

			String sql = "";
			//如果sortCode不为空，即走modelTypess_info,sortCode=pro_info的方式
			if (Validator.isNotNull(sortCode)) {
				Method method = IusSqlTools.class.getDeclaredMethod(modelTypes.substring(2) + "Sql", new Class[] {
						String.class, ParamsVo.class });
				sql = String.valueOf(method.invoke(this, modelTypes, vo));
			} else {
				//如果sortCode为空，则走modelTypes=s_TrpPro的方式

				sql = getSelectMoreSqlStr(vo, modelTypes.split(","), null);
			}

			return sql;
		} catch (Exception e) {
			throw new BusinessException(e.getMessage());
		}
	}

	public String dymicNativeSql(ParamsVo vo) {
		String execSql = "";
		String modelTypes = String.valueOf(vo.getParams("modelTypes"));
		if (Validator.isNotNull(modelTypes)) {//是否有需要修改的类型
			exeCustomPlugin(vo, "befor");
			if (Validator.isNotNull(String.valueOf(vo.getParams("plugin_execSql")))) {
				return String.valueOf(vo.getParams("plugin_execSql"));
			}
			String str[] = modelTypes.split(",");
			try {
				int count = str.length;
				if (modelTypes.startsWith("s_") && count > 1) {//多表联查
					execSql = getSelectMoreSqlStr(vo, str, "@");
				} else if (modelTypes.startsWith("s_") && count == 1) {//单表查询
					return selectNativeSql(vo);
				} else {
					for (int i = 0; i < str.length; i++) {//循环生成sql  (i_,u_,d_,ib_)
						execSql += dymicInsertSql(vo, str, i);
					}
				}
			} catch (Exception e) {
				throw new BusinessException(e.getMessage());
			}
		} else {
			execSql = String.valueOf(vo.getParams("execSql"));
		}
		return execSql;
	}

	private String dymicInsertSql(ParamsVo vo, String[] str, int i) throws NoSuchMethodException,
			IllegalAccessException, InvocationTargetException {
		String prefix = str[i].substring(2);
		if (str[i].startsWith("ib_")) {
			prefix = str[i].substring(3);
		}
		String attr = ToolsUtil.getInstance().getValueByKey("custom-method.properties", "obj_" + prefix);
		String sql = "";
		if (Validator.isNull(attr)) {//判断是否动态表单
			attr = this.densgerSql(vo, str[i].substring(2));
		}
		if (Validator.isNull(attr)) {
			Method method = IusSqlTools.class.getDeclaredMethod(str[i].substring(2) + "Sql", new Class[] {
					String.class, ParamsVo.class });
			sql = String.valueOf(method.invoke(this, str[i], vo));
		} else {
			String attrStr[] = attr.split(";");
			Map<String, String> params = IusClassUtil.getInstance().convert2Map(vo.getParams(), prefix);

			sql = dymicSql(str[i], vo, attrStr[2], attrStr[1], prefix, params, attrStr[3]);

			if (prefix.equalsIgnoreCase("trpRules")) {
				String rulesCode = String.valueOf(vo.getParams(prefix + ".rulesCode"));
				if (Validator.isNotNull(rulesCode)) {
					String rulesName = String.valueOf(vo.getParams(prefix + ".rulesName"));
					getPlugin().setPluginInfo(rulesCode, rulesName);
				}
			} else if (prefix.equalsIgnoreCase("trpPluginManager")) {
				CustomMethodFactory.getInstance().setPlugins(String.valueOf(vo.getParams(prefix + ".pluginShortName")),
						String.valueOf(vo.getParams(prefix + ".pluginFullName")));
			}
		}
		if (Validator.isNotNull(sql)) {
			sql = sql + ";";
		}
		return sql;
	}

	///////////////////////以下拼装对象sql///////////////////////////////////////////

	protected String userSql(String exeType, ParamsVo vo) {
		/***
		 * 不规范的表名与实体名（如UCT_USER表对应USER.java，应该是对应UctUser.java，需要这样写死
		 */
		vo.setParams(exeType + "_User", "uct_user");
		String result = reflection(exeType, vo, new User(), "user_id");
		return result;
	}

	protected String orgSql(String exeType, ParamsVo vo) {
		vo.setParams(exeType + "_Org", "uct_org");
		String result = reflection(exeType, vo, new Org(), "org_id");
		return result;
	}

	protected String memberSql(String exeType, ParamsVo vo) {
		vo.setParams(exeType + "_Member", "t_member");//不规范的表名与实体名（理由同上），需要这样写死
		String result = reflection(exeType, vo, new Member(), "member_id");
		return result;
	}

	protected String infoSql(String exeType, ParamsVo vo) {
		String sortCode = String.valueOf(vo.getParams("sortCode"));
		List<PubMetadata> list = InfoReleaseCoreCleint.getInstance().getMetadatas(sortCode);
		if (null == list)
			return "";
		Map<String, String> params = IusClassUtil.getInstance().convert2Map(vo.getParams(), "info");
		String attrStr = "";
		String primaryKeyId = "info_id";
		for (PubMetadata pm : list) {
			if ("1".equals(pm.getDataRestrict())) {//处理主键
				primaryKeyId = pm.getDataShortName();
			}
			attrStr += pm.getDataAttr() + ",";
		}
		invokePlugin(exeType, vo, "info", params);
		String tableName = upperCharToUnderLine("pub_" + sortCode);
		String result = dymicSql(exeType, vo, primaryKeyId, attrStr, "info", params, tableName);
		return result;
	}

	private String reflection(String exeType, ParamsVo vo, Object obj, String primaryKeyId) {
		String result = "";
		String attrStr = getReflectAttr(obj);
		String modelType = exeType.substring(2);
		Map<String, String> params = IusClassUtil.getInstance().convert2Map(vo.getParams(), modelType);
		invokePlugin(exeType, vo, modelType, params);
		String tableName = upperCharToUnderLine(obj.getClass().getSimpleName());
		if (Validator.isNotNull(String.valueOf(vo.getParams(exeType + "_" + obj.getClass().getSimpleName())))) {
			tableName = String.valueOf(vo.getParams(exeType + "_" + obj.getClass().getSimpleName()));
		}
		result = dymicSql(exeType, vo, primaryKeyId, attrStr, modelType, params, tableName);
		return result;
	}

	private void invokePlugin(String exeType, ParamsVo vo, String modelType, Map<String, String> params) {
		String keys = String.valueOf(vo.getParams("sqlKeyId"));
		String invokeMethodKey = String.valueOf(vo.getParams("invokeMethodKey"));
		if (Validator.isNotNull(keys)) {
			if (Validator.isNull(invokeMethodKey))
				return;
			ParamsVo pvo = new ParamsVo();
			pvo.setParams(params);
			pvo.setParams("sqlKeyId", keys);
			pvo.setParams("plugin_exeType", modelType);
			pvo.setMethodKey("invokeMethodKey");
			Map<String, Object> map = (Map) getPlugin().doInvoke(pvo);
			if (!Validator.isEmpty(map) && !map.isEmpty()) {
				for (String key : map.keySet()) {
					params.put(key, String.valueOf(map.get(key)));
				}
				vo.setParams("invokeMethodKey", "");
				vo.setParams("sqlKeyId", "");
			}
		} else {
			if (Validator.isNull(invokeMethodKey))
				return;
			CustomMethodPlugin plugin = CustomMethodFactory.getInstance().getPluginByKey(invokeMethodKey);
			if (!Validator.isEmpty(plugin)) {
				if (exeType.startsWith("i_") || exeType.startsWith("u_") || exeType.startsWith("d_")) {
					vo.setParams("plugin_exeType", modelType);
					Map<String, Object> map = (Map) plugin.doInvoke(vo.getParams());
					if (!Validator.isEmpty(map)) {
						for (String key : map.keySet()) {
							params.put(key, String.valueOf(map.get(key)));
						}
					}
					vo.setParams("invokeMethodKey", "");
				}
			}
		}
	}

	/**
	 * description:  生成插入语句
	 */
	public String createInsertSqlStr(Map<String, String> params, String modelType, ParamsVo paramVo) {
		String result = "";
		return result;
	}

	/**
	 * description:  生成修改语句
	 */
	public String createUpdateSqlStr(Map<String, String> params, String modelType, ParamsVo paramVo) {
		String result = "";
		return result;
	}
}
